// ScoreBoard.java
// Jim Sproch
// Created: April 29, 2006
// Modified: March 30, 2008
// Part of the Aforce Port
// Mac < Windows < Linux

/**
	ScoreBoard holds and displayes scores for players
	@author Jim Sproch
	@version 0.1a beta
*/

import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.awt.event.*;

import java.io.*;


public class ScoreBoard implements ActionListener, Serializable
{
	private static final int maxScores = 5;
	JFrame scoresFrame = null;
	JTextField usernamefield = null;
	JButton okButton = null;
	TreeSet<ScoreEntry> scores = new TreeSet<ScoreEntry>();
	boolean attemptingToAddNewScoreEntry = false;

	private static final long serialVersionUID = 7526471155622776148L;


	public static ScoreBoard getInstance()
	{
		ScoreBoard result = null;
		try {
			FileInputStream inFile = new FileInputStream("Data"+File.separator+"ScoreBoard.data");
			ObjectInputStream inStream = new ObjectInputStream(inFile);
			result = (ScoreBoard) inStream.readObject();
		} catch (Exception e) {
		}
		if(result != null) return result;
		else return new ScoreBoard();
	}

	public void add(AForce owner, int level, int score)
	{
		// There is no score board in applet mode, just start a new game :)
		if(AForce.isAppletMode())
		{
			owner.newGame();
			return;
		}

		attemptingToAddNewScoreEntry = true;
		usernameis("Penguin Tux"); // This sets all empty score fields to be owned by "Penguin Tux"
		scores.add(new ScoreEntry(level, score));
		buildGUI(owner);
		while(scores.size() > maxScores)
		{
			scores.remove(scores.first());  //cleanup old scores if any
		}
	}

	public JFrame getFrame()
	{
		return scoresFrame;
	}

	public void buildGUI(AForce owner)
	{
		if(AForce.isAppletMode()) return;

		scoresFrame = new JFrame();
	//	scoresFrame.addWindowListener(AForceMenu.getKeepUpInstance());
		scoresFrame.addWindowListener(new AForceMenu.KeepUp());
		scoresFrame.addWindowFocusListener((WindowFocusListener)scoresFrame.getWindowListeners()[0]);
		scoresFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		scoresFrame.setResizable(false);
		scoresFrame.setTitle("AForce ~ High Scores!");
		scoresFrame.setSize(350, 300);
		scoresFrame.setLocation(new Point(AForce.getFrame().getX()+scoresFrame.getX()+(int)scoresFrame.getSize().getWidth()/2, AForce.getFrame().getY()+scoresFrame.getY()+(int)scoresFrame.getSize().getHeight()/2));
		scoresFrame.getContentPane().setBackground(Color.gray);
		scoresFrame.setVisible(true);


		JPanel mainPanel = new JPanel();
		mainPanel.setLayout(GUI.gbl);
		scoresFrame.getContentPane().add(mainPanel);
			JPanel topPanel = new JPanel();
			topPanel.setLayout(new GridLayout(3,1));
			GUI.add(mainPanel, topPanel, 0, 0);
			GUI.add(topPanel, new JLabel("   AForce High Scores:"), 0, 0);

		JPanel listPanel = new JPanel();
		JPanel buttonPanel = new JPanel();

		int difference;
		if(maxScores > scores.size()) difference = maxScores-scores.size()+1;
		else difference = 0;
		listPanel.setLayout(new GridLayout(maxScores-difference+2,4));
		GUI.add(topPanel, listPanel, 0, 1);
			GUI.add(listPanel, new JLabel("Rank:       "), 0, 0);
			GUI.add(listPanel, new JLabel("Name:       "), 1, 0);
			GUI.add(listPanel, new JLabel("Level:      "), 2, 0);
			GUI.add(listPanel, new JLabel("Score:      "), 3, 0);

			Iterator<ScoreEntry> scoreIterator = scores.iterator();
			ScoreEntry currentScore = null;
			boolean madeHighScoreList = false;
			for(int currentScoreCount = 0; currentScoreCount < maxScores; currentScoreCount++)
			{
				if(scoreIterator.hasNext()) currentScore = scoreIterator.next();
				else break;

				if(currentScore.getUsername() == null) madeHighScoreList = true;

				GUI.add(listPanel, new JLabel(" "+(currentScoreCount+1)), 0, currentScoreCount+1);
				if(currentScore.getUsername() == null)
				{
					usernamefield = new JTextField();
					GUI.add(listPanel, usernamefield, 1, currentScoreCount+1);
				}
				else GUI.add(listPanel, new JLabel(currentScore.getUsername()+"  "), 1, currentScoreCount+1);
				GUI.add(listPanel, new JLabel("  "+currentScore.getLevel()), 2, currentScoreCount+1);
				GUI.add(listPanel, new JLabel(currentScore.getScore()+"   "), 3, currentScoreCount+1);
			}

		GUI.add(topPanel, buttonPanel, 0,2);
			okButton = new JButton("OK");
			okButton.addActionListener(this);
			GUI.add(buttonPanel, okButton, 0, 0);

			if(madeHighScoreList && attemptingToAddNewScoreEntry) AForceMenu.madeHighScoreList(scoresFrame, true);
			else if(attemptingToAddNewScoreEntry) AForceMenu.madeHighScoreList(scoresFrame, false);
			attemptingToAddNewScoreEntry = false;
			scoresFrame.setVisible(true);

	}


	public void actionPerformed(ActionEvent ae)
	{
		if(ae.getSource() == okButton)
		{
			if(scoresFrame != null) scoresFrame.dispose();
			scoresFrame = null;
			okButton = null;
			if(usernamefield != null) usernameis(usernamefield.getText());
			else usernameis("Penguin Tux");
			try {
				FileOutputStream outFile = new FileOutputStream("Data"+File.separator+"ScoreBoard.data");
				ObjectOutputStream outStream = new ObjectOutputStream(outFile);

				outStream.writeObject(this);

				}catch (IOException ex) {
				ex.printStackTrace();
			}
			
		}
	}

	public void usernameis(String username)
	{
		// This sets all unknown score entries to username.  If the previous user didn't enter his/her name
		//  It is there loss.  The name SHOULD be given to "Penguin Tux", but depending on implementation, it
		//  Could be given to the next player
		Iterator<ScoreEntry> index = scores.iterator();
		while(index.hasNext())
		{
			ScoreEntry currentScore = index.next();
			if(currentScore.getUsername() == null) currentScore.setUsername(username);
		}
	}


	public static class GUI
	{
		public static GridBagLayout gbl = new GridBagLayout();
		public static GridBagConstraints gbc = new GridBagConstraints();
		public static int currentrow = 0;

		public static void add(Container parent, Component child, int gridx, int gridy)
		{
			gbc.gridx = gridx;
			gbc.gridy = gridy;
			gbl.setConstraints(child, gbc);
			parent.add(child);
		}
	}
}


class ScoreEntry implements Comparable<ScoreEntry>, Serializable
{
	String username = null;
	int level;
	int score;

	private static final long serialVersionUID = 7526471155622776147L;

	public ScoreEntry(int level, int score)
	{
		this.level = level;
		this.score = score;
	}
	public ScoreEntry(String username, int level, int score)
	{
		this.level = level;
		this.score = score;
		this.username = username;
	}

	public void setUsername(String username)
	{
		this.username = username;
	}

	public String getUsername()
	{
		return username;
	}

	public int getLevel()
	{
		return level;
	}

	public int getScore()
	{
		return score;
	}

	public int compareTo(ScoreEntry obj)
	{
		if(this.equals(obj)) return 0; // If the objects have same memory address (really are same)
		ScoreEntry other = (ScoreEntry)obj;
		if(this.getLevel() != other.getLevel()) return other.getLevel() - this.getLevel();
		if(this.getScore() != other.getScore()) return other.getScore() - this.getScore();
		return -1;
	}

	public boolean equals(Object obj)
	{
		if(this.toString().equals(obj.toString())) return true;
		return false;
		 // If the objects have same memory address (really are same)
	}

	public static void main(String[] args)
	{
		Printer.noexecute();
	}
}

